package com.aos.iot.protocol.hll.parser;

import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import com.aos.iot.socket.common.message.Message;
import com.aos.iot.socket.common.parser.DataParserFactor;
import com.aos.iot.socket.common.parser.Parser;
import com.aos.iot.protocol.hll.util.CodeUtil;
import com.aos.iot.protocol.hll.message.HllMessage;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import static com.aos.iot.protocol.hll.constant.HllConstant.PROTOCOL_NAME;

@Component
@RequiredArgsConstructor
public class HllParser implements Parser<HllMessage> {

    private final DataParserFactor dataParserFactor;

    @Override
    public HllMessage encode(Message.Direction direction, String payload) {
        HllMessage message = new HllMessage();
        message.setHead(sub(payload, 0, 4, false, "55AA"));
        message.setVersion(sub(payload, 4, 6, false, "00"));
        message.setEncrypt(sub(payload, 6, 8, false, "00"));
        message.setLength(sub(payload, 8, 12, true, "0000"));
        message.setLengthInt(HexUtil.hexToInt(message.getLength()));
        message.setSn(sub(payload, 12, 14, false, "00"));
        message.setCmd(sub(payload, 14, 16, false, "00"));
        message.setDataContext(sub(payload, 16, 16 + message.getLengthInt() * 2 - 6, false, ""));
        message.setData(dataParserFactor.getDataParser(protocol(), message.getCmd()).encode(message.getDataContext()));
        message.setSign(sub(payload, payload.length() - 2, payload.length(), false, "00"));
        return message;
    }

    @Override
    public String decode(HllMessage message) {
        String dataHex = dataParserFactor.getDataParser(message.getProtocol(), message.getCmd()).decode(message.getData());
        message.setDataContext(dataHex);
        int dataLength = (StrUtil.length(dataHex) + 6) / 2;
        message.setLengthInt(dataLength);
        String dataLengthHex = CodeUtil.highRotation(String.format("%04x", dataLength));
        message.setLength(dataLengthHex);
        String sign = CodeUtil.sign(message.getVersion(), message.getEncrypt(), message.getLength(), message.getSn(), message.getCmd(), message.getDataContext());
        message.setSign(sign);
        return StrUtil.join("",
                message.getHead(),
                message.getVersion(),
                message.getEncrypt(),
                message.getLength(),
                message.getSn(),
                message.getCmd(),
                message.getDataContext(),
                message.getSign()
        );
    }

    @Override
    public boolean confirm(HllMessage message) {
        if(message.getDirection() == Message.Direction.DOWN) {
            String sign = CodeUtil.sign(message.getVersion(), message.getEncrypt(), message.getLength(), message.getSn(), message.getCmd(), message.getDataContext());
            return StrUtil.equalsIgnoreCase(sign, message.getSign());
        }
        return true;
    }

    @Override
    public String protocol() {
        return PROTOCOL_NAME;
    }


}
